% -*- Mode: TeX -*-
% Copyright 2007 TeX Users Group.
% You may freely use, modify and/or distribute this file.

% Merging PostScript Illustrations

% These TeX macros enable easy insertion of PostScript
% illustrations into documents produced by TeX and LaTeX.
% The illustrations are automatically sized when the
% PostScript file has a
%    BoundingBox: llx lly urx ury
% line in it.  The units of measurement for lower-left-x (llx),
% lower-left-y (lly), upper-right-x (urx), and
% upper-right-y (ury) are 1/72 of an inch (a PostScript unit).

% Source locations at the MIT AI Laboratory
%   Canonical Source
%     Trix      /homes/glr/tex/psadobe/psadobe.tex

% References
%   Adobe Systems, Inc
%     PostScript Language Reference Manual
%     Addison-Wesley, 1986
%     Appendix C, pages 279-286
%   DVILASER/PS User Manual
%     ArborText, Inc, 1987

% Copyright Gerald Roylance 1987, 1989
%   This file may be copied or distributed as long as this
%   copyright notice is not removed.

% PostScript is a trademark of Adobe Systems Incorporated.

% Bugs and Fixes
%   bulletproof reading the postscript file [GLR, 11/89]
%     reads only the headercomments, demands %! and %%
%   add ArborText support [GLR, 3/89]
%   clear out some junk [GLR, 3/89]
%   convert \mag to a float at runtime [Rich, 12/87]
%   removed spurious cr's in psadobeextract, -bb, -header [Rich, 11/87]
%   make psfile switch to horizontal mode 
%     now LaTeX \leavevmode isn't needed [GLR, 11/87]
%   changed \errmessage to \message for file not found
%     in \psadobeheader [Rich, 12/87]
%   added \psadobepercent [Rich, 12/87]
%   added \xpsadobe and \xpsadobepercent [Rich, 2/22]


% Usage

% To load the macros, use
%       \input{psadobe}
% The macros are read from TeX's default input area.

% To insert an illustration, use
%       \psadobe{filename.ps}
% The expression is treated exactly like a character.
% You will probably want to center it or use other positioning
% commands.  The illustration is also magnified by the \mag
% parameter.  If you don't want this magnification, then
% use
%       \psadobenomag{filename.ps}

% The filename may present some difficulty because
% both TeX and the dvi converter use the filename.
% You may have to provide a fully qualified filename.

% The illustrations to be inserted with autosizing must use
% the Adobe PostScript File Structuring Conventions (PFSC).
% These macros do automatic sizing of the inserted illustation
% by reading the PFSC header comment of the PostScript file.
% The Lisp Machine program Illustrate produces the correct format.
% Most MacIntosh programs do not provide a tight bounding box.

% In order to insert a PostScript file, the .dvi to PostScript
% converter must implement \special{PSFILE...} or use ArborText's
% \special{ps:...} commands.  The MIT AI Lab uses the Unix program
% dvi2ps (available from ???) and a Lisp Machine dvi converter
% (available from the Symbolics LispMachine Users' Group).

% If your converter cannot understand a set of special commands,
% then after loading psadobe turn off the appropriate set of specials:
%       \dvitopsfalse
%       \ArborTextfalse

% For further information, see MIT AI Laboratory Working Paper 299a.


% Subroutines

\newif\ifdvitops   \dvitopstrue		% include PSFILE specials
\newif\ifArborText \ArborTexttrue	% include ArborText specials

% The fundamental insertion macro.  This inserts a PostScript file
% putting the origin at (x,y) and building a TeX box whose
% size is (w,h).  Nothing fancy is done.  x,y,w,h are TeX dimensions.
% The magnification m is a string that should be something like 1.40.
%
% psfile(x,y,w,h,m,filename)
%
\newbox\psvoid
%
\def\psfile#1#2#3#4#5#6{%
  \unhbox\psvoid%	switch to horizontal mode (just like a letter would)
  \hbox to #3{%		make a box w wide
     \kern-#1%		offset the illustration's x-pos
     \vbox to #4{%	make a box h tall
        \vfil%		push the special down to the bottom
        \kern#2%	offset by the illustration's y-pos
        \ifdvitops\special{psfile=#6 hscale=#5 vscale=#5}\fi%
	\ifArborText%
	   \special{ps::[asis,begin]
		0 SPB
		/PSFileCheckPoint save def
		/showpage  {} def
		/erasepage {} def
		/copypage  {} def
		/letter    {} def
		/note      {} def
		/legal     {} def
		/ledger    {} def
		/11x17     {} def
		/a3        {} def
		/a4        {} def
		Xpos Ypos translate
		#5 dup scale
		/xdefaultmatrix matrix currentmatrix def
		/defaultmatrix {xdefaultmatrix exch copy} def
		/initmatrix    {xdefaultmatrix setmatrix} def
		/initgraphics
		  {initmatrix newpath initclip
		   1 setlinewidth 0 setlinecap 0 setlinejoin
		   [] 0 setdash 0 setgray 10 setmiterlimit} def
		}%
	   \special{ps: plotfile #6 asis}%
	   \special{ps::[asis,end]
		PSFileCheckPoint restore
		0 SPE }%
	   \fi%
        \kern-#2}%	unoffset y
     \kern#1\hfil%	unoffset x and push the special left
     }}

% Convert an integer to a floating point string.
% This gross hack works if \mag < 10000
%
\newcount\float \float=\mag \advance\float by 10000
\def\floater#1#2#3#4#5{#2.#3#4#5}


% Parse a PostScript Header

% The header looks like
%
%    %!PS-Adobe-1.0
%    %%Creator: Illustrate Version 11.0
%    %%CreationDate: 6/23/87 17:35:01
%    %%Pages: 1
%    %%BoundingBox: 466.12912 718.63934 612.0283 792.0283
%    %%EndComments
%
% *** Should complain if #2 is (atend)

% Dimensions of the illustration
\newdimen\psadobex
\newdimen\psadobey
\newdimen\psadobew
\newdimen\psadobeh

\newif\ifpsadobeflag

\newread\psadobefile

% set the default values for the bounding box
% either
%   \psadobesetdefault{72}{72}{72}{72}{}
%   \psadobesetdefault{72}{72}{72}{72}{true}
%
\def\psadobesetdefault#1#2#3#4#5{%
  \global\psadobex= #1 #5bp%		set the default sizes to 72 points
  \global\psadobey= #2 #5bp%
  \global\psadobew= #3 #5bp%
  \global\psadobeh= #4 #5bp}

% psadobeextract(junk llx lly urx ury true)

% PostScript and TeX share the same comment character, and now TeX must
% look for that comment character in a PostScript file.  So turn % into
% regular character.  Unfortunately, that gives us trouble with line
% breaks -- we can no longer put % at the end of a line.
% One fix, due to Chuck Rich, just cleverly (and unreadably) puts the
% line breaks where they are ignored.
% Another fix temporarily redefines ~ as a comment character.

\catcode`\%=12
\catcode`\~=14

~ psadobeextract expects to be called with the box size and
~ some trailing garbage left over from reading the line.
~ \psadobeextract %%BoundingBox: llx lly urx ury %%BoundingBox:\heaven{true}

\def\psadobeextract#1 #2 #3 #4 #5%%BoundingBox:\heaven#6{~
  \global\psadobex= #2 #6bp~
  \global\psadobey= #3 #6bp~
  \global\psadobew= #4 #6bp~
  \global\advance\psadobew by -\psadobex~
  \global\psadobeh= #5 #6bp~
  \global\advance\psadobeh by -\psadobey}

\def\psadobebb#1%%BoundingBox:#2\EOL#3{~
  \ifx#2\heaven~			if second arg is the token \heaven
    \else~				otherwise
      \psadobeflagfalse~		 stop looking
      \psadobeextract#2{#3}~		 extract the bounding box
      \closein\psadobefile~		 and close the file
    \fi}

~ psadobeheader takes 2 arguments.  The first is either {} or {true};
~ {} means use normal (with magnification) sizes and {true} means
~ use actual sizes (no magnifcation).  The second argument is the name
~ of the PostScript file.
~
\def\psadobeheader#1#2{~
  \openin\psadobefile=#2~		open the PostScript file
  \relax~
  \ifeof\psadobefile~			check if the file is there
    \message{psadobe did not find PostScript file #2}~
   \else~
    \begingroup~			save the character definitions
       \def\psadobeendcom{%%EndComments}~
       \def\psadobefirst ##1%!##2\EOL{~	make sure line starts with %!
         \ifx##2\heaven~
	   \psadobeflagfalse~		set the exit flag
           \message{psadobe: file #2 does not start with a %! comment.
	            Please add PostScript header comments to the file.}~
	   \else\fi}~
       \def\psadoberest ##1%%##2\EOL{~	make sure line starts with %%
         \ifx##2\heaven~
	   \psadobeflagfalse~		set the exit flag
	   \else\fi}~
       \catcode`\^^M=10~		make sure CR is a space (obeylines)
       \catcode`\%=12~			turn off % comments (12 = other)
       ~				... should turn off other characters
       \psadobeflagtrue~		loop until this psadobeflag is false
       \read\psadobefile to \line~	read the first line
       ~				check first line starts with %!
       \expandafter\psadobefirst\line %!\heaven\EOL~
       \loop~				read each header line
         \ifeof\psadobefile~		if end of file
	   \psadobeflagfalse~		  set the exit flag
	   \message{psadobe hit EOF looking for BoundingBox in #2.
	            Please put a BoundingBox comment in the header.}~
          \else~
           \read\psadobefile to \line~	read a line from the ps file
	   ~				check the line starts with %%
           \expandafter\psadoberest\line %%\heaven\EOL~
	   \ifx\line\psadobeendcom~	if the line is %%EndComments
	     \psadobeflagfalse~		  then the header has ended
	    \else\fi~
           \ifpsadobeflag~		if it's a good header comment, test for BBox
             \expandafter\psadobebb\line %%BoundingBox:\heaven\EOL{#1}~
            \else~			otherwise we didn't find a BBox
             \message{psadobe did not find a BoundingBox comment in #2.
	              Please put one in.}~
            \fi~
          \fi~
         \ifpsadobeflag\repeat~
       \endgroup\fi}

\catcode`\%=14
\catcode`\~=13

% Normal comments are back on now.


% Automatic Sizing of a PostScript File

% These are the advertised calls.
%   Everything else may change.

% Insert a Postscript file with scaling by \mag
%
\def\psadobe#1{\xpsadobe{#1}{#1}}

% Following auxiliary definition allows a different pathname syntax
% to be used on Tex'ing machine versus dvi->ps machine.
% [Float mag has to be done here because of expansion problems -- CR]
%
\def\xpsadobe#1#2{%
  \psadobesetdefault{72}{72}{72}{72}{}%	set the default sizes to 72 points
  \psadobeheader{}{#1}%			parse the header comments
  {\float=\mag \advance\float by 10000%
   \psfile{\psadobex}{\psadobey}{\psadobew}%
         {\psadobeh}{\expandafter\floater\the\float}{#2}}}

% Insert a PostScript file without scaling by \mag
%   read header using true dimensions
%   insert the file with a magnification of 1
\def\psadobenomag#1{%
  \psadobesetdefault{72}{72}{72}{72}{true}%  set the default sizes to 72 points
  \psadobeheader{true}{#1}%		parse the header comments
  \psfile{\psadobex}{\psadobey}{\psadobew}{\psadobeh}{1.000}{#1}}

% Insert a PostScript file, scaling by current value of \mag and a given percent
% N.B. The first argument is the *percent* scaling (i.e. 100 is normal size).
%
% psadobepercent( percent, file )

\def\psadobepercent#1#2{\xpsadobepercent{#1}{#2}{#2}}

% Similarly to \xpsadobe

\def\xpsadobepercent#1#2#3{%
  \psadobesetdefault{72}{72}{72}{72}{}%  set the default sizes to 72 points
  \psadobeheader{}{#2}%			parse the header comments
  \global\divide\psadobex by 100\global\multiply\psadobex by #1%
  \global\divide\psadobey by 100\global\multiply\psadobey by #1%
  \global\divide\psadobew by 100\global\multiply\psadobew by #1%
  \global\divide\psadobeh by 100\global\multiply\psadobeh by #1%
  {\float=\mag \multiply\float by #1\divide\float by 100%
	\advance\float by 10000%
	  \psfile{\psadobex}{\psadobey}{\psadobew}%
	       {\psadobeh}{\expandafter\floater\the\float}{#3}}}

\ArborTextfalse % avoid those nasty PSLASER type special commands!

\endinput

